#ifndef _SEETANET_FORWARD_H_
#define _SEETANET_FORWARD_H_

// @todo define int64_t before VS2010
#include <stdint.h>
#include <stdlib.h>
#include "SeetaNetStruct.h"

#define SEETANET_MAJOR_VERSION 0
#define SEETANET_MINOR_VERSION 7
#define SEETANET_SINOR_VERSION 7

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Read all content from the given file, into an binary memory buffer
* @param [in] file_name The file ready to read.
* @param [out] pbuffer A pointer pointing a binary memory buffer.
* @param [out] file_length Returning the size of the read buffer.
* @return Return 0 only if everything is OK.
* @note Required to call @c SeetaFreeBuffer with the unused memory buffer, free the memory.
* @see SeetaFreeBuffer
*/
SEETANET_C_API int SeetaReadAllContentFromFile( const char *file_name, char **pbuffer, int64_t *file_length );

/**
* @brief Free a binary memory buffer.
* @param [in] buffer the buffer generated by @c SeetaReadAllContentFromFile, ready to finalize.
* @see SeetaReadAllContentFromFile
*/
SEETANET_C_API void SeetaFreeBuffer( char *buffer );

/**
* @brief Init the model configuration from the given memory buffer (with length).
* @param [in] buffer Pointing to a binary protobuf object in memory.
* @param [in] buffer_length The size of the `buffer`.
* @param [out] pmodel A pointer pointing a @c SeetaNet_Model pointer. Returning an inner model structure.
* @return Return 0 only if everything is OK.
* @note Required to call @c SeetaReleaseModel with `model`, finalizing the inner model structure.
* @see SeetaNet_Model SeetaReleaseModel
*/
SEETANET_C_API int SeetaReadModelFromBuffer( const char *buffer, size_t buffer_length, struct SeetaNet_Model **pmodel );

/**
 * @brief Set input image width and height in FCN net
 * @param [in] model The model generated by @c SeetaReadModelFromBuffer.
 * @param [in] width new width of forward net
 * @param [in] height new height of forward net
 * @return Return 0 only if everything is OK.
 * @note width and heigth can be 0, means using default size
 */
SEETANET_C_API int SeetaModelResetInput( struct SeetaNet_Model *model, int width, int height );

/**
* @brief Finalize the inner model structure.
* @param [in] model A pointer pointing a @c SeetaNet_Model, ready to finalize.
* @see SeetaNet_Model
*/
SEETANET_C_API void SeetaReleaseModel( struct SeetaNet_Model *model );

/**
* @brief Get the default device, @c SEETANET_GPU_DEVICE only returned in gpu version
* @return Return 0 only if everything is OK.
* @see SeetaNet_DEVICE_TYPE SEETANET_GPU_DEVICE
*/
SEETANET_C_API enum SeetaNet_DEVICE_TYPE SeetaDefaultDevice();


/**
* @brief Create the net from the given model configuration.
* @param [in] model The model generated by @c SeetaReadModelFromBuffer.
* @param [in] max_batch_size The max batch size you can feed.
* @param [in] process_device_type Chose the device running net. See @see SeetaNet_DEVICE_TYPE.
* @param [out] pnet A pointer pointing a @c SeetaNet_Net pointer. Returning an inner net structure.
* @return Return 0 only if everything is OK. May return error UNIDENTIFIED_LAYER
* @note Required to call @c SeetaReleaseNet with `net`, finalizing the inner net structure.
* @see SeetaReadModelFromBuffer SeetaNet_Net SeetaReleaseNet
*/
SEETANET_C_API int SeetaCreateNet( struct SeetaNet_Model *model, int max_batch_size, enum SeetaNet_DEVICE_TYPE process_device_type, struct SeetaNet_Net **pnet );


/**
* @brief Create the net from the given model configuration.
* @param [in] model The model generated by @c SeetaReadModelFromBuffer.
* @param [in] max_batch_size The max batch size you can feed.
* @param [in] process_device_type Chose the device running net. See @see SeetaNet_DEVICE_TYPE.
* @param [out] pnet A pointer pointing a @c SeetaNet_Net pointer. Returning an inner net structure.
* @param [out] pparam A pointer pointing a @c SeetaNet_SharedParam pointer. Returning an inner param structure.
* @return Return 0 only if everything is OK. May return error UNIDENTIFIED_LAYER
* @note Required to call @c SeetaReleaseNet with `net`, finalizing the inner net structure.
* @see SeetaReadModelFromBuffer SeetaNet_Net SeetaReleaseNet
*/
SEETANET_C_API  int SeetaCreateNetSharedParam( struct SeetaNet_Model *model, int max_batch_size, enum SeetaNet_DEVICE_TYPE process_device_type, struct SeetaNet_Net **pnet, struct SeetaNet_SharedParam **pparam );


/**
 * @brief Get net shared param
 * @param [in] net The net generated by @c SeetaCreateNet.
 * @return A pointer pointing a @c SeetaNet_SharedParam pointer.
 */
SEETANET_C_API struct SeetaNet_SharedParam *SeetaGetSharedParam( struct SeetaNet_Net *net );

/**
 * @brief Keep blob by name, so that @c SeetaGetFeatureMap can get
 * @param [in] net The net generated by @c SeetaCreateNet.
 * @param [in] blob_name The blob's name ready to keep
 */
SEETANET_C_API void SeetaKeepBlob( struct SeetaNet_Net *net, const char *blob_name );

/**
 * @brief Do not keep any blob when compling.
 * @param [in] net The net generated by @c SeetaCreateNet.
 */
SEETANET_C_API void SeetaKeepNoBlob( struct SeetaNet_Net *net );

/**
 * @brief Keep all blob when compling.
 * @param [in] net The net generated by @c SeetaCreateNet.
 */
SEETANET_C_API void SeetaKeepAllBlob( struct SeetaNet_Net *net );

/**
 * @brief Return the `blob_name` if kept
 * @param [in] net The net generated by @c SeetaCreateNet.
 * @return return non-zero if the `blob_name` is kept
 */
SEETANET_C_API int SeetaHasKeptBlob( struct SeetaNet_Net *net, const char *blob_name );

/**
* @brief Finalize the inner net structure.
* @param [in] net A pointer pointing a @c SeetaNet_Net, ready to finalize.
* @see SeetaNet_Net
*/
SEETANET_C_API void SeetaReleaseNet( struct SeetaNet_Net *net );

/**
* @brief Feed the data @c SeetaNet_InputOutputData into the net, and do "Forward Propagation"
* @param [in] net The net generated by @c SeetaCreateNet.
* @param [in] counts Not used reserve parameter, 1 fro default.
* @param [in] pinput_data The data feed the `net`
* @return Return 0 only if everything is OK.
* @note The `pinput_data->data_point_char` means the input data
* @see SeetaNet_InputOutputData SeetaCreateNet
*/
SEETANET_C_API int SeetaRunNetChar( struct SeetaNet_Net *net, int counts, struct SeetaNet_InputOutputData *pinput_data );

/**
* @brief Feed the data @c SeetaNet_InputOutputData into the net, and do "Forward Propagation"
* @param [in] net The net generated by @c SeetaCreateNet.
* @param [in] counts Not used reserve parameter, 1 fro default.
* @param [in] pinput_data The data feed the `net`
* @return Return 0 only if everything is OK.
* @note The `pinput_data->data_point_float` means the input data
* @see SeetaNet_InputOutputData SeetaCreateNet
*/
SEETANET_C_API int SeetaRunNetFloat( struct SeetaNet_Net *net, int counts, struct SeetaNet_InputOutputData *pinput_data );

/**
* @brief Get the output @c SeetaNet_InputOutputData data after last time @c SeetaRunNetChar
* @param [in] net The net generated by @c SeetaCreateNet.
* @param [in] blob_name Which blob you want get.
* @param [out] poutput_data The gotten data.
* @return Return 0 only if everything is OK.
* @see SeetaNet_InputOutputData SeetaRunNetChar SeetaCreateNet
*/
SEETANET_C_API int SeetaGetFeatureMap( struct SeetaNet_Net *net, const char *blob_name, struct SeetaNet_InputOutputData *poutput_data );

SEETANET_C_API int SeetaGetAllFeatureMap( struct SeetaNet_Net *net, int *number, struct SeetaNet_InputOutputData **poutput_data );

SEETANET_C_API void SeetaFreeAllFeatureMap( struct SeetaNet_Net *net, const struct SeetaNet_InputOutputData *poutput_data );

/**
 * @biref free all temp, after no API of seetanet could be called
 */
SEETANET_C_API void SeetaFinalizeLibrary();

/**
 * @biref return an string contain the version, like 0.7.4
 * @return library version string
 * @note the memory is kept in library, no need to free
 */
SEETANET_C_API const char *SeetaLibraryVersionString();



#ifdef __cplusplus
}
#endif

#endif
